import tkinter as tk
from tkinter import *
from tkinter.ttk import Treeview
import tkinter.messagebox
from tkinter import ttk


bg = "#F0F8FF"  # 背景颜色

y = 1  # 行
product_list = {}  # 产生式集合

terminal_char = []


# 窗口居中
def CenterWindow(window, width, height, bg=bg):
    window.configure(bg=bg)  # 背景颜色
    # 设置窗口居中
    screenwidth = window.winfo_screenwidth()
    screenheight = window.winfo_screenheight()
    alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
    window.geometry(alignstr)
    # 设置窗口大小不可改变
    window.resizable(width=False, height=False)


# 判断产生式左边是否正确   规则：1、只能为大写字母，且数量为一个
def is_left_correct(str: str):
    if len(str) == 0 or len(str) > 1:
        tk.messagebox.showerror('提示', '左边只能为大写字母且数量是1，请检查！！')
        return False
    elif str >= 'A' and str <= 'Z':
        return True
    tk.messagebox.showerror('提示', '左边只能为大写字母且数量是1，请检查！！')
    return False


# 判断产生式右边是否正确   规则：1、不能含空格2、不能含数字3、@后不能含任何元素
def is_right_correct(str: str):
    if len(str) == 1 and str[0] == '@':
        return True
    for index in range(len(str)):
        if str[index] == '@' and len(str) != 1:
            tk.messagebox.showerror('提示', '@前后不能含任何元素，请检查！！')
            return False
    return True


# 双击列表行   修改产生式
tip = False  # 是否不显示提示


def treevie_double_wclick(event, tree, e1, e2):
    global y
    if len(tree.selection()) == 0:
        return ""
    global tip, product_list

    for item in tree.selection():
        item_text = tree.item(item, "values")
        tree.delete(item)
        product_list[item_text[1]].remove(item_text[3])
        if len(product_list[item_text[1]]) == 0:
            product_list.pop(item_text[1])
        e1.delete(0, "end")
        e2.delete(0, "end")
        e1.insert("end", item_text[1])
        e2.insert("end", item_text[3])

    # 重新排序
    sort_tree(tree)

    if not tip:
        tip = tkinter.messagebox.askyesno('提示', '所选数据已返回，请修改后重新提交\n是否不再提示（是  or  否）？')


# 添加产生式按钮
def btn_add_data(e1, e2, tree):
    global product_list
    left = e1.get()
    right = e2.get()
    if len(left) == 0 or len(right) == 0:
        tk.messagebox.showerror('提示', '不能空输入！！')
        return ""
    if not is_left_correct(left):
        return ""
    if not is_right_correct(right):
        return ""
    # 判断是否已存在该字典key值
    # 存在key值
    if left in product_list.keys():
        # 若重复  提示重复
        if right in product_list[left]:
            tk.messagebox.showerror('提示', '不能输入重复的产生式！！')
            return ""
        # 若不重复  直接添加
        else:
            product_list[left].append(right)
    # 不存在key值
    # 添加列表
    else:
        product_list[left] = [right]
    # 添加数据
    add_data(left, right, tree)
    sort_tree(tree)
    e1.delete(0, "end")
    e2.delete(0, "end")


# 给列表添加数据
def add_data(left, right, tree):  # 添加数据
    global y
    tree.insert("", "end", values=(y, left, "-->", right))
    y += 1


# 清空列表
def clear_tree(tree, clear_pro=False):
    global product_list
    item_list = tree.get_children()
    for item in item_list:
        tree.delete(item)
    if clear_pro:
        product_list.clear()
    # print(product_list)


# 获取第二个参数
def take_second(elemt):
    return elemt[1]


# 获取第一个参数
def take_first(elemt):
    return elemt[0]


# 排序表格
def sort_tree(tree):
    global y
    y = 1
    data_list = []
    item_list = tree.get_children()
    for item in item_list:
        item_text = tree.item(item, "values")
        data_list.append(item_text)
    clear_tree(tree)
    data_list.sort(key=take_second)
    for item in data_list:
        add_data(item[1], item[3], tree)


def create_tree(window, cols):
    # 表格窗体容器
    frame = Frame(window, bg=bg)
    frame.pack()
    ybar = Scrollbar(frame, orient='vertical')  # 竖直滚动条
    # 表格
    style = ttk.Style(window)
    # set ttk theme to "clam" which support the fieldbackground option
    style.theme_use("clam")
    style.configure("Treeview", background=bg,
                    fieldbackground=bg, foreground="green")
    tree = Treeview(frame, show='headings', columns=cols, yscrollcommand=ybar.set, height=12, selectmode="browse")

    ybar['command'] = tree.yview

    tree.grid(row=0, column=0)  # grid方案
    ybar.grid(row=0, column=1, sticky='ns')

    return tree


def create_tree_goto_action(window, cols_goto, cols_action, window_width):
    # goto表格窗体容器
    goto_frame = Frame(window, bg=bg)
    goto_frame.place(x=10, y=21)
    goto_ybar = Scrollbar(goto_frame, orient='vertical')  # 竖直滚动条
    # 表格
    style = ttk.Style(window)
    # set ttk theme to "clam" which support the fieldbackground option
    style.theme_use("clam")
    style.configure("Treeview", background=bg,
                    fieldbackground=bg, foreground="green")
    tree_goto = Treeview(goto_frame, show='headings', columns=cols_goto, yscrollcommand=goto_ybar.set, height=24,
                         selectmode="browse")

    goto_ybar['command'] = tree_goto.yview

    tree_goto.grid(row=0, column=0)  # grid方案
    goto_ybar.grid(row=0, column=1, sticky='ns')

    # action表格窗体容器
    action_frame = Frame(window, bg=bg)
    action_frame.place(x=window_width - 220, y=21)
    action_ybar = Scrollbar(action_frame, orient='vertical')  # 竖直滚动条
    # 表格
    tree_action = Treeview(action_frame, show='headings', columns=cols_action, yscrollcommand=action_ybar.set,
                           height=24, selectmode="browse")

    action_ybar['command'] = tree_action.yview

    tree_action.grid(row=0, column=0)  # grid方案
    action_ybar.grid(row=0, column=1, sticky='ns')

    return [tree_goto, tree_action]


# 初始化窗口
def init_window():
    window = tk.Tk()
    window.title("LR0分析表")
    CenterWindow(window, 400, 410, bg)
    lable = tk.Label(window, text="产生式( 双击修改，重新写入 ),结束符为 #", bg=bg)
    lable.pack()
    lable2 = tk.Label(window, text="请不要写‘ | ’，产生式右边为单独整体，默认为空（@）", bg=bg)
    lable2.pack()

    cols = ["行", "左边", "箭头", "右边"]  # 数据
    tree = create_tree(window, cols)  # 创建表格

    tree.heading('行', text="行")
    tree.heading('左边', text="左边")
    tree.heading('箭头', text="箭头")
    tree.heading('右边', text="右边")
    tree.column('行', width=25, anchor=S)  # 定义列
    tree.column('左边', width=60, anchor=S)  # 定义列
    tree.column('箭头', width=40, anchor=S)  # 定义列
    tree.column('右边', width=150, anchor=S)  # 定义列

    tree.bind('<Double-Button-1>', lambda event: treevie_double_wclick(event, tree, e1, e2))  # 双击事件绑定

    e1 = Entry(window, width=6, fg='green')
    e1.place(x=80, y=320)
    lable_jiantou = Label(window, text="-->", bg=bg)
    lable_jiantou.place(x=140, y=320)
    e2 = Entry(window, width=10, fg='green')
    e2.place(x=175, y=320)
    btn_add = Button(window, text="添加产生式", command=lambda: btn_add_data(e1, e2, tree), bg=bg)

    btn_add.place(x=280, y=318)

    LR0_btn = tk.Button(window, text="求LR0", activebackground="#40E0D0", bg=bg, command=LR0_table)
    # SLR1_btn = tk.Button(window, text="求SLR(1)", activebackground="#40E0D0", bg=bg, command=SLR1_table)
    btn_y = 350
    btn_x = 80
    btn_w = 70
    btn_h = 40
    LR0_btn.place(x=btn_x, y=btn_y, width=btn_w, height=btn_h)
    # SLR1_btn.place(x=btn_x + 100, y=btn_y, width=btn_w + 15, height=btn_h)

    btn_delete = tk.Button(window, text="清空表格", command=lambda: clear_tree(tree, True), bg=bg,
                           activebackground="#40E0D0")
    btn_delete.place(x=btn_x + 200, y=btn_y, width=btn_w, height=btn_h)

    '''测试数据'''
    '''测试数据一'''  # 符合LR(0)文法
    add_data('E', 'TB#', tree)
    add_data('B', '+TB', tree)
    add_data('T', 'FC', tree)
    add_data('C', '*FC', tree)
    add_data('F', '(E)', tree)
    add_data('F', 'i', tree)
    sort_tree(tree)
    product_list['B'] = ['+TB']
    product_list['C'] = ['*FC']
    product_list['E'] = ['TB#']
    product_list['F'] = ['(E)', 'i']
    product_list['T'] = ['FC']

    '''测试数据二'''  #
    # add_data('S', 'AB', tree)
    # add_data('A', 'Da', tree)
    # add_data('B', 'cC', tree)
    # add_data('C', 'aADC', tree)
    # add_data('D', 'b', tree)
    # sort_tree(tree)
    # product_list['S'] = ['AB']
    # product_list['A'] = ['Da']
    # product_list['B'] = ['cC']
    # product_list['C'] = ['aADC']
    # product_list['D'] = ['b']

    '''测试数据三'''  #
    # add_data('S', 'AB', tree)
    # add_data('S', 'bC', tree)
    # add_data('A', 'b', tree)
    # add_data('B', 'aD', tree)
    # add_data('C', 'AD', tree)
    # add_data('C', 'b', tree)
    # add_data('D', 'aS', tree)
    # add_data('D', 'c', tree)
    # sort_tree(tree)
    # product_list['S'] = ['AB', 'bC']
    # product_list['A'] = ['b']
    # product_list['B'] = ['aD']
    # product_list['C'] = ['AD', 'b']
    # product_list['D'] = ['aS', 'c']

    '''测试数据'''
    window.mainloop()


# 关闭窗口
def close_window(window):
    window.destroy()


# 判断字符类型
def type_char(c):
    if c >= 'A' and c <= 'Z':
        return 'N'  # 非终结符
    return 'T'  # 终结符


# 创建终结符集合
def create_terminal():
    global terminal_char, product_list
    terminal_char.clear()
    for key in product_list.keys():
        for item in product_list[key]:
            for index in range(len(item)):
                if type_char(item[index]) == 'T' and item[index] not in terminal_char and item[index] != '@':
                    terminal_char.append(item[index])
    if '#' not in terminal_char:
        terminal_char.append('#')


node_dic = {}  # 装全部节点  每个node_index  对应一个  node


class node:
    def __init__(self, name):
        self.next_node_dic = {}  # 装可以进行的输入，有了这个输入就可以转换到另一个节点，即每个输入对应一个   key为输入   node(node的下标 node_index)为结果
        self.this_node_product_dic = {}  # 当前节点含有的产生式，含点（.）作为记号
        self.name = str(name)
        global node_dic, product_list
        node_dic[name] = self
        self.node_index = name
        for key in product_list.keys():
            self.this_node_product_dic[key] = []

    # 添加下一个节点    每个key对应一个节点 状态
    def add_next_node(self, key, index_node):
        self.next_node_dic[key] = index_node

    # 添加this_node_product_list当前节点含的产生式
    def add_product(self, left, right):
        self.this_node_product_dic[left].append(right)

    # 返回节点的index，用于查找节点
    def get_node_index(self):
        return self.node_index

    # 返回节点的this_node_product_dic
    def get_this_node_product_dic(self):
        return self.this_node_product_dic

    # 返回节点的next_node_dic
    def get_next_node_dic(self):
        return self.next_node_dic

    # 打印节点信息
    def print_node(self):
        print('---------------------------')
        print("序号：", self.node_index)
        print("产生式：")
        for key in self.this_node_product_dic.keys():
            for item in self.this_node_product_dic[key]:
                print(key, " --> ", item)
        print('--------------------------')


# 构建LR0自动机
node_num = 1
have_next_node = []  # 存储已被分析过邻接节点的节点
new_node = []  # 存储没有被分析过邻接节点的节点


def automaton_LR0(product_dic, start_char):
    global node_num, have_next_node, new_node
    node_left = []  # 该节点的产生式左部   待展开的非终结符
    node_left.append(start_char)  # 刚开始左部只有start_char
    # 创建开始节点
    start_node = node(node_num)
    new_node.append(start_node)
    node_num += 1

    index = 0
    while True:
        if index == len(node_left):  # 展开完成   退出展开
            break
        for item in product_dic[node_left[index]]:  # 展开该非终结符的所有内容
            start_node.add_product(node_left[index], "." + item)  # 首位加点，作为  活前缀  记号
            if type_char(item[0]) == 'N':  # 若点下一个字符为 非终结符，则添加到待展开列表
                if item[0] not in node_left:  # 防止重复
                    node_left.append(item[0])
        index += 1  # 扫描下一个非终结符
    # print("分析序号：",start_node.node_index)
    analyse_next_node(start_node, product_dic)
    have_next_node.append(start_node)  # 添加到已被分析的节点列表
    new_node.remove(start_node)  # 从new_node列表删除元素

    while True:
        # print(len(new_node))
        if len(new_node) == 0:
            break
        # print("分析序号：", new_node[0].node_index)
        # print( new_node[0].get_this_node_product_dic())
        analyse_next_node(new_node[0], product_dic)
        have_next_node.append(new_node[0])  # 添加到已被分析的节点列表
        new_node.remove(new_node[0])  # 从new_node列表删除元素
    return have_next_node


# 根据 father_node 找出与他连接的下一个节点
def analyse_next_node(father_node, product_dic):
    global node_num, node_dic, have_next_node, new_node
    father_node_product = father_node.get_this_node_product_dic()  # 获取产生式

    node_str_dic = {}
    # 扫描产生式，以确定下一节点
    for key in father_node_product.keys():
        for item in father_node_product[key]:
            item = str(item)
            pos_point = item.find('.')
            if pos_point == len(item) - 1:  # 到达末尾，规约状态    没有下一个节点
                pass
            else:  # 未到达末尾  可以产生下一个状态，移动点 . 即可（交换与点 . 相邻的两个字符）
                str_temp = item[pos_point] + item[pos_point + 1]
                str_temp = item.replace(str_temp, str_temp[::-1])
                if str_temp[pos_point] not in node_str_dic.keys():
                    node_str_dic[str_temp[pos_point]] = []
                node_str_dic[str_temp[pos_point]].append([key, str_temp])

    # 开始分析father的邻接节点
    for key in node_str_dic.keys():
        node_temp = node(node_num)  # 每个key对应一个节点

        node_left = []  # 待展开的非终结符

        for item in node_str_dic[key]:
            node_temp.add_product(item[0], item[1])  # 添加初始产生式

            item = str(item)
            # 根据初始产生式，开始分析，是否展开点 . 相邻的非终结符
            pos_point = item.find('.')
            if len(item) - 1 != pos_point:  # 没有到达末尾
                if item[pos_point + 1] not in node_left and type_char(item[pos_point + 1]) == 'N':
                    node_left.append(item[pos_point + 1])  # 假如待展开的非终结符
        index_node_left = 0
        while True:  # 展开node_temp所有的点相邻的 非终结符（node_left里所有的）
            if index_node_left == len(node_left):  # 所有非终结符已经展开  则该节点 简化完成
                break
            for item in product_dic[node_left[index_node_left]]:  # 展开该非终结符的所有内容
                node_temp.add_product(node_left[index_node_left], "." + item)  # 首位加点，作为  活前缀  记号
                if type_char(item[0]) == 'N':  # 若点下一个字符为 非终结符，则添加到待展开列表
                    if item[0] not in node_left:  # 防止重复
                        node_left.append(item[0])
            index_node_left += 1  # 扫描下一个非终结符

        # 判断该节点是否已存在，若重复内容，表示已存在，否则表示不存在，可以创建
        node_temp_product = node_temp.get_this_node_product_dic()
        should_node_num_add = True
        for key_2 in node_dic.keys():
            if key_2 != node_num:
                # print(key,node_num)
                node_pro = node_dic[key_2].get_this_node_product_dic()  # 已有的产生式状态
                if node_pro != node_temp_product:
                    # print(node_pro,"与",node_temp_product,"不相同")
                    continue
                else:
                    # print(node_pro,"与",node_temp_product,"相同")
                    father_node.add_next_node(key, key_2)  # 添加入father节点的下一节点字典中   指向已有的产生式状态
                    should_node_num_add = False  # 重复，则跳出判断
                    break
        if should_node_num_add:
            node_num += 1  # node数量+1
            father_node.add_next_node(key, node_temp.get_node_index())  # 添加入father节点的下一节点字典中
            new_node.append(node_temp)  # 添加到new_node里

    # print("father为：")
    # father_node.print_node()
    # print("child为：")
    # childs = father_node.get_next_node_dic()
    # for key in childs.keys():
    #     print("输入 ",key,"得到child状态：")
    #     child = node_dic[childs[key]]
    #     child.print_node()


def tree_of_preview(window, node_index, frame_x, frame_y):
    left = " "
    right = "  "
    cols = [left, "序号" + node_index, right]
    # 表格窗体容器
    frame = Frame(window, bg=bg)
    frame.place(x=frame_x, y=frame_y)
    ybar = Scrollbar(frame, orient='vertical')  # 竖直滚动条
    # 表格
    style = ttk.Style(window)
    # set ttk theme to "clam" which support the fieldbackground option
    style.theme_use("clam")
    style.configure("Treeview", background=bg,
                    fieldbackground=bg, foreground="green")
    tree = Treeview(frame, show='headings', columns=cols, yscrollcommand=ybar.set, height=5,
                    selectmode="browse")

    ybar['command'] = tree.yview

    tree.grid(row=0, column=0)  # grid方案
    ybar.grid(row=0, column=1, sticky='ns')

    tree.heading(left, text=left)
    tree.heading("序号" + node_index, text="序号" + node_index)
    tree.heading(right, text=right)
    tree.column(left, width=25, anchor=S)  # 定义列
    tree.column("序号" + node_index, width=60, anchor=S)  # 定义列
    tree.column(right, width=100, anchor='w')  # 定义列
    return tree


def preview_node(all_node_list: dict):
    window = tk.Tk()
    window.title("预览节点")
    CenterWindow(window, 1280, 710, bg)
    x_int = 210  # 每个卡片的间隔，横向间隔
    y_int = 200  # 每个卡片的间隔，纵向间隔
    now_x_y = [0,0]
    tree_num = 0
    for node_temp in all_node_list:#dict为每个index对应一个node
        node_product_temp = node_temp.get_this_node_product_dic()#每个键值对应一个list

        tree_temp = tree_of_preview(window,str(node_temp.get_node_index()),now_x_y[0],now_x_y[1])
        now_x_y[0] += x_int
        tree_num += 1
        if tree_num == 6:
            now_x_y[0] = 0
            now_x_y[1] += y_int
            tree_num = 0
        for key_temp in node_product_temp.keys():
            data = ()
            for item in node_product_temp[key_temp]:#扫描每个item填入卡片

                data += (key_temp,"-->",item,)
                tree_temp.insert("", "end", values=data)
                data = ()

#判断文法是否符合LR0文法
def is_correct_LR0(product_dic:dict):
    all_item = []
    #判断产生式是否能产生空
    for key in product_dic.keys():
        for item in product_dic[key]:
            all_item.append(item)
            if '@' == item:
                tk.messagebox.showerror('提示', '产生式能产生空 @！！移进-规约冲突，不符合LR（0）文法！！')
                return False
    all_item.sort()
    #判断是否两个右部相同
    for index in range(len(all_item)-1):#
        if all_item[index] == all_item[index+1]:
            tk.messagebox.showerror('提示', '产生式两个右部相同产生：'+all_item[index]+'，规约-规约冲突，不符合LR（0）文法！！！！')
            return False
    return True

# 得到LR0的action表和goro表
def LR0_table():
    global terminal_char, product_list, node_dic,have_next_node
    if not is_correct_LR0(product_list):
        return ""

    # 创建终结符集合
    create_terminal()

    cols_goto = ['行']  # 列数据
    cols_action = ['行', 'Action']  # 列数据
    window_width = 50
    for item in terminal_char:
        cols_goto.append(item)
        window_width += 40

    for key in product_list.keys():
        cols_goto.append(key)
        window_width += 40
    window_width += 250

    LR0_window = Tk()
    LR0_window.title("LR0表")
    CenterWindow(LR0_window, window_width, 600)

    def init_LR0_window(label_temp, btn, E):
        LR0_window.wm_attributes('-topmost', 0)
        start_c = E.get()

        #若开始的产生式没有结束符，则自动加上
        for index in range(len(product_list[start_c])):
            item_index = product_list[start_c][index]
            if '#' not in item_index:
                product_list[start_c][index] = product_list[start_c][index]+'#'


        if start_c < 'A' or start_c > 'Z':
            tk.messagebox.showerror('提示', '请输入大写字符！！')
            LR0_window.wm_attributes('-topmost', 1)
            return ""
        elif start_c not in product_list.keys():
            tk.messagebox.showerror('提示', '没有该产生式！！请检查！！')
            LR0_window.wm_attributes('-topmost', 1)
            return ""
        label_temp.destroy()
        btn.destroy()
        E.destroy()
        label = Label(LR0_window, text="LR(0) Goto表", bg=bg)
        label.place(x=100, y=0)
        label2 = Label(LR0_window, text="LR(0) Action表", bg=bg)
        label2.place(x=window_width - 150, y=0)
        close_btn = tk.Button(LR0_window, text="关闭", activebackground="#40E0D0", bg=bg,
                              command=lambda: close_window(LR0_window))
        close_btn.place(x=220, y=550, width=100, height=50)
        preView_btn = tk.Button(LR0_window, text="预览每个序号的节点内容", activebackground="#40E0D0", bg=bg,
                                command=lambda: preview_node(have_next_node))
        preView_btn.place(x=420, y=550, width=200, height=50)

        tree_goto_action = create_tree_goto_action(LR0_window, cols_goto, cols_action, window_width)  # 创建表格
        tree_goto = tree_goto_action[0]
        tree_action = tree_goto_action[1]
        for col in cols_goto:
            tree_goto.heading(col, text=col)
            tree_goto.column(col, width=40, anchor=S)  # 定义列

        tree_action.heading(cols_action[0], text=cols_action[0])
        tree_action.column(cols_action[0], width=40, anchor=S)  # 定义列
        tree_action.heading(cols_action[1], text=cols_action[1])
        tree_action.column(cols_action[1], width=150, anchor=S)  # 定义列

        all_node = automaton_LR0(product_list, start_c)
        # 获取分析数据
        for node_item in all_node:
            data_goto = ()
            data_action = ()
            line = node_item.get_node_index()
            data_goto += (line,)
            data_action += (line,)
            temp = tree_goto.insert("", "end", values=data_goto)
            for key in node_item.get_next_node_dic().keys():
                tree_goto.set(temp, column=key, value=node_item.get_next_node_dic()[key])

            if node_item.get_next_node_dic() != {}:  # 含下一个节点   要执行Shift操作
                data_action += ('Shift',)
                tree_action.insert("", "end", values=data_action)
                # print(node_item.get_next_node_dic())
            else:  # 不含下一个操作，操作分为Reduce  或  Accept
                is_Accept = False
                node_item_pro = node_item.get_this_node_product_dic()
                for key_pro in node_item_pro.keys():
                    if len(node_item_pro[key_pro]) == 0:
                        continue
                    if '#.' in node_item_pro[key_pro][0]:
                        is_Accept = True
                    str_reduce_or_accept = node_item_pro[key_pro][0].replace('.', '')
                    key_str = key_pro
                if is_Accept:
                    data_action += ('Accept :  ' + key_str + " --> " + str_reduce_or_accept,)
                    tree_action.insert("", "end", values=data_action)
                else:
                    data_action += ('Reduce :  ' + key_str + " --> " + str_reduce_or_accept,)
                    tree_action.insert("", "end", values=data_action)

    label = Label(LR0_window, text="请输入开始字符:", bg=bg)
    label.place(x=10, y=200)
    comvalue = tkinter.StringVar()  # 窗体自带的文本，新建一个值
    start_char = ttk.Combobox(LR0_window, textvariable=comvalue, width=10)  # 初始化下拉列表
    N_T_char = ()  # 记录全部非终结符
    for key in product_list.keys():
        N_T_char += (key,)
    start_char["values"] = N_T_char
    start_char.current(0)  # 选择第一个作为开始字符
    start_char.place(x=120, y=200)
    btn_sure = Button(LR0_window, text="确定", command=lambda: init_LR0_window(label, btn_sure, start_char), bg=bg,
                      activebackground="#40E0D0", width=4, height=2)
    btn_sure.place(x=250, y=190)

if __name__ == "__main__":
    init_window()

